package com.masonluo.mlonlinejudge.acl.proxy;

import com.masonluo.mlonlinejudge.acl.core.AuthenticationIdentificationAchiever;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
 * @author masonluo
 * @date 2021/5/5 8:04 下午
 */
public class ProxyBean {

    /**
     * 需要代理的原对象
     */
    private final Object origin;

    /**
     * 保存着需要代理的方法和执行该方法之前所需要执行的方法的Map
     * key为代理的方法
     * value为执行该代理方法之前需要执行的方法
     */
    private final Map<Method, MethodWrapper> proxyMethod = new HashMap<>();

    private final MethodWrapper afterInterceptReturnMethod;

    private final AuthenticationIdentificationAchiever metadataAchiever;

    public ProxyBean(Object origin, MethodWrapper afterInterceptReturnMethod, AuthenticationIdentificationAchiever metadataAchiever) {
        this.origin = origin;
        this.afterInterceptReturnMethod = afterInterceptReturnMethod;
        this.metadataAchiever = metadataAchiever;
    }

    public Object getOrigin() {
        return origin;
    }

    public Map<Method, MethodWrapper> getProxyMethod() {
        return proxyMethod;
    }

    public MethodWrapper getAfterInterceptReturnMethod() {
        return afterInterceptReturnMethod;
    }

    public AuthenticationIdentificationAchiever getMetadataAchiever() {
        return metadataAchiever;
    }

    public void put(Method method, MethodWrapper beforeMethod) {
        proxyMethod.put(method, beforeMethod);
    }

    public MethodWrapper get(Method method) {
        return proxyMethod.get(method);
    }

    public static class MethodWrapper {
        private final Method method;

        private final Object executeObj;

        public MethodWrapper(Method method, Object executeObj) {
            this.method = method;
            this.executeObj = executeObj;
        }

        public Method getMethod() {
            return method;
        }

        public Object getExecuteObj() {
            return executeObj;
        }

        public Object invoke(Object[] args) throws InvocationTargetException, IllegalAccessException {
            return method.invoke(executeObj, args);
        }
    }
}
